// for atmega8L
// from http://www.scienceprog.com/generate-sine-wave-modulated-pwm-with-avr-microcontroller/

// ATMEL ATMEGA8
//
//       +-\/-+
// PC6  1|    |28  PC5
// PD0  2|    |27  PC4	
// PD1  3|    |26  PC3
// PD2  4|    |25  PC2
// PD3  5|    |24  PC1
// PD4  6|    |23  PC0
// VCC  7|    |22  GND
// GND  8|    |21  AREF
// PB6  9|    |20  AVCC
// PB7 10|    |19  PB5
// PD5 11|    |18  PB4
// PD6 12|    |17  PB3
// PD7 13|    |16  PB2
// PB0 14|    |15  PB1
//       +----+



// On the Arduino board, digital pins are also used
// for the analog output (software PWM).  Analog input
// pins are a separate set.

// ATMEL ATMEGA8 & 168 / ARDUINO
//
//                  +-\/-+
//            PC6  1|    |28  PC5 (AI 5)
//      (D 0) PD0  2|    |27  PC4 (AI 4)
//      (D 1) PD1  3|    |26  PC3 (AI 3)
//      (D 2) PD2  4|    |25  PC2 (AI 2)
// PWM+ (D 3) PD3  5|    |24  PC1 (AI 1)
//      (D 4) PD4  6|    |23  PC0 (AI 0)
//            VCC  7|    |22  GND
//            GND  8|    |21  AREF
//            PB6  9|    |20  AVCC
//            PB7 10|    |19  PB5 (D 13)
// PWM+ (D 5) PD5 11|    |18  PB4 (D 12)
// PWM+ (D 6) PD6 12|    |17  PB3 (D 11) PWM
//      (D 7) PD7 13|    |16  PB2 (D 10) PWM
//      (D 8) PB0 14|    |15  PB1 (D 9) PWM
//                  +----+
//
// (PWM+ indicates the additional PWM pins on the ATmega168.)


#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>

const uint8_t sinewave[] PROGMEM = //256 values
{
	0x80,0x83,0x86,0x89,0x8c,0x8f,0x92,0x95,0x98,0x9c,0x9f,0xa2,0xa5,0xa8,0xab,0xae,
	0xb0,0xb3,0xb6,0xb9,0xbc,0xbf,0xc1,0xc4,0xc7,0xc9,0xcc,0xce,0xd1,0xd3,0xd5,0xd8,
	0xda,0xdc,0xde,0xe0,0xe2,0xe4,0xe6,0xe8,0xea,0xec,0xed,0xef,0xf0,0xf2,0xf3,0xf5,
	0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfc,0xfd,0xfe,0xfe,0xff,0xff,0xff,0xff,0xff,
	0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfe,0xfd,0xfc,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,
	0xf6,0xf5,0xf3,0xf2,0xf0,0xef,0xed,0xec,0xea,0xe8,0xe6,0xe4,0xe2,0xe0,0xde,0xdc,
	0xda,0xd8,0xd5,0xd3,0xd1,0xce,0xcc,0xc9,0xc7,0xc4,0xc1,0xbf,0xbc,0xb9,0xb6,0xb3,
	0xb0,0xae,0xab,0xa8,0xa5,0xa2,0x9f,0x9c,0x98,0x95,0x92,0x8f,0x8c,0x89,0x86,0x83,
	0x80,0x7c,0x79,0x76,0x73,0x70,0x6d,0x6a,0x67,0x63,0x60,0x5d,0x5a,0x57,0x54,0x51,
	0x4f,0x4c,0x49,0x46,0x43,0x40,0x3e,0x3b,0x38,0x36,0x33,0x31,0x2e,0x2c,0x2a,0x27,
	0x25,0x23,0x21,0x1f,0x1d,0x1b,0x19,0x17,0x15,0x13,0x12,0x10,0x0f,0x0d,0x0c,0x0a,
	0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x03,0x02,0x01,0x01,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x05,0x06,0x07,0x08,
	0x09,0x0a,0x0c,0x0d,0x0f,0x10,0x12,0x13,0x15,0x17,0x19,0x1b,0x1d,0x1f,0x21,0x23,
	0x25,0x27,0x2a,0x2c,0x2e,0x31,0x33,0x36,0x38,0x3b,0x3e,0x40,0x43,0x46,0x49,0x4c,
	0x4f,0x51,0x54,0x57,0x5a,0x5d,0x60,0x63,0x67,0x6a,0x6d,0x70,0x73,0x76,0x79,0x7c
};
// index
uint8_t i = 0; // can only have values within [0,255]

// interrupt
ISR(TIMER1_COMPA_vect) 
{
	//Altering the value of the Output Compare Registers (OCR) changes the duty cycle. 
	//Increasing the OCR value increases the duty cycle. The PWM output is high until the 
	//OCR value is reached, and low until the timer reaches the top value and wraps back to 
	//0. This is called Fast-PWM mode.
	OCR1A = pgm_read_byte(&sinewave[i]); // set PWM to value
	i++;
}

int main(void) 
{
	// INPUT
	//Port D pins as input
	DDRD=0x00;
	//Enable internal pull ups
	PORTD=0xFF;
	
	// PWM
	//Set PORTB1 pin as output
	DDRB=0x02;//0xFF;
	
	//initial OCR1A value (Pulse Width)
	OCR1A=80; // PULSE WIDTH ([0x00,0xFF])
	
	//In the AVR, the timer/counters are used to generate PWM signals. To change the PWM 
	//base frequency, the timer clock frequency and top counter value is changed. Faster 
	//clock and/or lower top value will increase the PWM base frequency, or timer overflow 
	//frequency. With full resolution (top value 255) the maximum PWM base frequency is 
	//250 kHz. Increasing the base frequency beyond this frequency will be at the expense of 
	//reduced resolution, since fewer step are then available from 0% to 100% duty cycle. 
	
	//16 bit timer counter maximum value may reach 65535. In AVR microcontrollers 16 bit timer
	//is Timer1. It contains a 16 bit input capture register (ICR1) and two 16 bit output 
	//compare registers (OCR1A and OCR1B).
	
	//Output compare OC1A 8 bit non inverted PWM
	TCCR1A=0x91;
	//start timer without prescaler
	TCCR1B=0x01;
	//enable output compare interrupt for OCR1A
	TIMSK=0x10;
	
	//Few words about prescaler. As timer counter is a binary counter it has a prescaler like 
	//other timers in AVR microcontrollers. Prescaler may be selected in TCCR1B with bits 
	//CS12, CS11 and CS10 like in 8 bit timers.
	
	
	//enable global interrups
	sei();
	
	while (1) 
	{
		//loop for ever. Interrupts will do the job.
	}
}
